#include "internal.h"
#include "Defines.h"
#include "Thread.h"

unsigned int __stdcall ThreadStub( void *lpObject );	//the actual thread function

CThread::CThread()
{
	threadID = 0;
	hThread = 0;
	hTerminateEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}

CThread::~CThread()
{
	if( hThread )
	{
		if( getExitCode() == STILL_ACTIVE )	//if thread is still running we need to stop
			stop();							//it, otherwise _CloseHandle_ below would raise
											//an exception
		CloseHandle( hThread );
		CloseHandle( hTerminateEvent );
	}
}

bool CThread::start( bool suspended )
{
	if( hThread )	//if thread is already running, stop it
		stop();

	//
	// reset event
	//
	ResetEvent(hTerminateEvent);

	//
	// set the ball rolling
	//
	hThread = (HANDLE)_beginthreadex( NULL,
									  0,
									  ThreadStub,
									  (void *)this,
									  ( suspended ) ? CREATE_SUSPENDED : 0,
									  &threadID );
	if( !hThread )
		return false;

	return true;
}

void CThread::stop( unsigned long exitCode )
{
	if( hThread )
		TerminateThread( hThread, exitCode );

	hThread = 0;
	threadID = 0;
}

void CThread::sleep( unsigned long msecs )
{
	//
	// Causes whatever happens to be the current thread (i.e., the thread that calls
	// this function) to sleep.
	//
	Sleep( msecs );
}

unsigned long CThread::getExitCode()
{
	if( !hThread )
		return 0;

	unsigned long exitCode = 0;
	GetExitCodeThread( hThread, &exitCode );

	return exitCode;
}

unsigned long CThread::getID()
{
	return threadID;
}

HANDLE CThread::getHandle()
{
	return hThread;
}

int CThread::getPriority()
{
	if( !hThread )
		return 0;

	return GetThreadPriority( hThread );
}

bool CThread::setPriority( int priority )
{
	if( !hThread )
		return false;

	if( SetThreadPriority( hThread, priority ) )
		return true;
	return false;
}

HANDLE CThread::getCurrentHandle()	//returns pseudo-thread handle to current thread
{
	return GetCurrentThread();
}

unsigned long CThread::getCurrentID()	//returns a unique pseudo-ID to current thread
{
	return GetCurrentThreadId();
}

unsigned long CThread::suspend()
{
	if( !hThread )
		return 0;

	return SuspendThread( hThread );
}

unsigned long CThread::resume()
{
	if( !hThread )
		return 0;

	return ResumeThread( hThread );
}

bool CThread::notifyTerminate()
{
	if(!hThread || !hTerminateEvent)
		return false;

	return (SetEvent(hTerminateEvent) == TRUE);
}

//
// the actual thread function that boot-straps the whole thing
//
unsigned int __stdcall ThreadStub( LPVOID lpObject )
{
	CThread *pThread = ( CThread * )lpObject;
	unsigned long result = pThread->run();
	_endthreadex( result );
	return result;
}
